﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;

namespace Zhongy
{
    public class TimerManager:MananerBase
    {
        public static TimerManager Instance = null;

        private IDictionary<int,TimerNormal> normalDic = new Dictionary<int, TimerNormal>();
        private IDictionary<int, TimerFixed> fixedDic = new Dictionary<int, TimerFixed>();
        private IList<int> removeLst = new List<int>();

        void Awake()
        {
            Instance = GetComponent<TimerManager>();


        }

        public int AddNormalTimer(int count, Action every, Action finish,int interval)
        {
            int id = GetTimerId();
            TimerNormal normal = new TimerNormal(id, count, every, finish, interval);
            normalDic.Add(id,normal);

            return id;
        }

        public int AddFixedTimer(int count, Action every, Action finish, int interval)
        {
            int id = GetTimerId();
            TimerFixed fix = new TimerFixed(id, count, every, finish, interval);
            fixedDic.Add(id,fix);

            return id;
        }

        public void Remove(int id)
        {
            if (!removeLst.Contains(id))
                removeLst.Add(id);
        }

        double nowTime = getMillTimer();
        void Update()
        {
            nowTime = getMillTimer();
            RemoveTimer();
            CheckNormalTimer(nowTime);
            CheckFixedTimer(nowTime);
        }

        void RemoveTimer()
        {
            if(removeLst.Count<=0)
                return;

            for (int i = removeLst.Count-1; i >=0; i++)
            {
                if (fixedDic.ContainsKey(removeLst[i]))
                {
                    TimerFixed timer = fixedDic[removeLst[i]];
                    fixedDic.Remove(removeLst[i]);
                    removeLst.RemoveAt(i);

                    timer.OnDispose();
                }

                if (normalDic.ContainsKey(removeLst[i]))
                {
                    TimerNormal timer = normalDic[removeLst[i]];
                    normalDic.Remove(removeLst[i]);
                    removeLst.RemoveAt(i);

                    timer.OnDispose();
                }
            }
        }

        void CheckNormalTimer(double nowTime)
        {
            if (normalDic.Count <= 0)
                return;
            
            var ier = normalDic.GetEnumerator();

            while (ier.MoveNext())
            {
                if (ier.Current.Value.Invaild)
                {
                    Remove(ier.Current.Key);
                }
                else
                {
                    ier.Current.Value.check(nowTime);
                }
            }
        }

        void CheckFixedTimer(double nowTime)
        {
            if (fixedDic.Count <= 0)
                return;

            var ier = fixedDic.GetEnumerator();

            while (ier.MoveNext())
            {
                ier.Current.Value.check(nowTime);
            }
        }

        private static int timerID= 0;
        public static int GetTimerId()
        {
            timerID++;
            if (timerID >= Int32.MaxValue)
                timerID = 0;

            return timerID;
        }

        static DateTime dt1970 = new DateTime(1970, 1, 1, 0, 0, 0, 0);

        public static double getMillTimer()
        {
            TimeSpan ts = DateTime.UtcNow - dt1970;
            return ts.TotalMilliseconds;
        }

        public static double getSecTimer()
        {
            TimeSpan ts = DateTime.UtcNow - dt1970;
            return ts.TotalSeconds;
        }
    }



    public abstract class TimerModel
    {
        public bool oneShot;

        public int id;
        public int count;
        public int interval;
        protected Action everyFunc;
        protected Action finishFunc;

        protected bool invalid = false;

        protected double startTime = 0;
        public bool Invaild
        {
            get { return invalid; }
        }

        public TimerModel()
        {
        }

        public TimerModel(int id, int count, Action everyFunc, Action finishFunc,int interval =-1)
        {
            this.startTime = TimerManager.getMillTimer();

            this.id = id;
            this.count = count;
            this.everyFunc = everyFunc;
            this.finishFunc = finishFunc;
            this.interval = interval;
        }

        protected int nowCount = 0;
        public virtual void check(double now)
        {

            if (now - startTime > interval && !invalid)
            {
                nowCount++;
                if (everyFunc != null)
                    everyFunc();
                if (nowCount >= count)
                {
                    if (finishFunc != null)
                    {
                        finishFunc();
                    }
                    invalid = true;
                }
                now = startTime;
            }
        }


        public void OnDispose()
        {
            everyFunc = null;
            finishFunc = null;
        }
    }

    public class TimerFixed : TimerModel
    {

        public TimerFixed(int id, int count, Action everyFunc, Action finishFunc, int interval = -1)
            : base(id, count, everyFunc, finishFunc, interval)
        {
        }

        public override void check(double now)
        {

            if (now - startTime > interval && !invalid)
            {
                //nowCount++;
                if (everyFunc != null)
                    everyFunc();

                startTime = now;
            }
        }
    }

    public class TimerNormal : TimerModel
    {
        public TimerNormal(int id, int count, Action everyFunc, Action finishFunc, int interval = -1)
            : base(id, count, everyFunc, finishFunc, interval)
        {

        }


    }

}
